<?php

/**
 * @author chenshubo
 * 订单取消
 */
namespace App\Service\OrderService\OrderInterfaceService;

use App\Service\Code\Normal;
use App\Service\BaseService;
use App\Model\PssModel\OrderSupplier;
use App\Model\PssModel\OrderSupplierGoods;
use App\Model\CommodityModel\SupplierCompany;
use App\Service\TaskServer\TaskWorker;
use App\Service\AppService\PushOrderSettleMentService;
use App\Model\PssModel\OrderReturnLog;
use App\Model\PssModel\Business;
use App\Service\CommodityService\CommodityStockService;
use App\Service\Volidate\OrderCreateVolidate;
use App\Service\OrderService\OrderSupplierEventLogMessageService AS OSELMS;

class OrderCancel extends BaseService
{
    /**
     * 订单取消接口模型
     */
    public function index( $param = [] )
    {
        if( empty($param['requestData']) ) {
            return Normal::returnCode(Normal::FAIL,"requestData参数不能为空");
        }

        $requestData = $param['requestData'];
        if( empty($requestData['orderSn']) ) {
            return Normal::returnCode(Normal::FAIL,"orderSn订单号不能为空");
        }
        
        if( empty($requestData['exceptReason']) ) {
            return Normal::returnCode(Normal::FAIL,"exceptReason取消订单原因不能为空");
        }
        
        //判断是否是子订单发起取消动作
        if( isset($requestData['isSingleOrder']) && $requestData['isSingleOrder'] == 1 && empty($requestData['orderNo']) ) {
            return Normal::returnCode(Normal::FAIL,"供应商订单号orderNo不能为空");
        }
        
        //根据原始订单号查询商户的
        $orderSn      = checkFields($requestData['orderSn']);
        $exceptReason = checkFields($requestData['exceptReason']);
        if( $orderSn != $requestData['orderSn'] ) {
            return Normal::returnCode(Normal::FAIL,"orderSn订单号不能包含特殊字符");
        }

        $res = $this->getSupplierOrderLists($param);
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }
        
        $res['data']['order'] = $param['requestData'];
        $res['data']['binfo'] = $param['binfo'];
        
        //判断是否是子订单发起取消
        if( isset($requestData['isSingleOrder']) && $requestData['isSingleOrder'] == 1 ) {
            $orderInfo      = current($res['data']['supplierOrderList']);
            $suppplierList  = $res['data']['suppplierList'];
            $orderGoodsList = $res['data']['newOrderGoods'];
            return $this->singleOrderCancel([
                'companyInfo'   => $suppplierList[$orderInfo['company_id']],
                'supplierOrder' => $orderInfo,
                'orderGoods'    => $orderGoodsList[$orderInfo['id']],
                'order'         => $res['data']['order'],
                'binfo'         => $res['data']['binfo']
            ]);
        }
        
        $res['data']['serviceClass'] = static::class;
        $res['data']['serviceMethod'] = "singleOrderCancel";
        $res = TaskWorker::instance()->addTask($res['data'],'singleOrder');
        $message = implode(",", array_column($res,'msg'));
        $code = array_column($res, 'code');
        if( in_array('0', $code) ) {
            return Normal::returnCode(Normal::FAIL,"处理完成；【{$message}】",$res);
        }
        return Normal::returnCode(Normal::SUC,"处理完成；【{$message}】",$res);
    }
    
    /**
     * 上游供应商发起取消动作，只需要更新本地数据
     */
    public function supplierCancel( $param = [] )
    {
        $requestData = $param['requestData'];
        if( empty($requestData['orderNo']) ) {
            return Normal::returnCode(Normal::FAIL,"except param OrderNo");
        }
        
        if( empty($requestData['orderCode']) ) {
            return Normal::returnCode(Normal::FAIL,"except param OrderCode");
        }
        
        $requestData['exceptReason'] = isset($requestData['exceptReason']) && !empty($requestData['exceptReason']) ? $requestData['exceptReason'] : '上游通知取消';
        if( empty($requestData['exceptReason']) ) {
            return Normal::returnCode(Normal::FAIL,"exceptReason取消订单原因不能为空");
        }
        
        if( empty($requestData['source']) ) {
            return Normal::returnCode(Normal::FAIL,"source来源不能为空");
        }
        
        $supplierOrder = OrderSupplier::instance()->info([
            'supplier_csn' => $requestData['orderCode'],
            'supplier_dsn' => $requestData['orderNo']
        ]);
        
        if( empty($supplierOrder) ) {
            return Normal::returnCode(Normal::SUC,"订单信息不存在");
        }
        
        //是否处理待取消的状态
        if( !in_array($supplierOrder['order_status'], [0,1,200,100] ) ) {
            return Normal::returnCode(Normal::SUC,"当前订单已发货，不能进行取消");
        }
        
        //判断当前订单是否已取消
        if( $supplierOrder['order_status'] == 100 ) {
            return Normal::returnCode(Normal::SUC,"当前订单已取消");
        }
        
        //当前订单是否已经取消，进行售后
        if( ($supplierOrder['order_type'] == 0 && $supplierOrder['after_sale_status'] == 1) || ($supplierOrder['order_type'] == 1 && $supplierOrder['after_verify_status'] > 1) ) {
            return Normal::returnCode(Normal::SUC,"已售后成功");
        }
        
        //获取供应商订单对应的商品
        $orderGoods = OrderSupplierGoods::instance()
        ->select(OrderSupplierGoods::instance()->goods_fields)
        ->where('bid',$supplierOrder['bid'])
        ->where('order_id',$supplierOrder['id'])
        ->get()
        ->toArray();
        if( empty($orderGoods) ) {
            return Normal::returnCode(Normal::FAIL,"获取订单数据失败");
        }
        
        //组装传入参数
        $param = [
            'order'         => [
                'exceptReason'          => $requestData['exceptReason'],
                'source'                => $requestData['source'],
                'is_supplier_cancel'    => 1,
            ],
            'supplierOrder' => $supplierOrder,
            'orderGoods'    => $orderGoods,
        ];
        
        OrderSupplier::instance()->startTrans();
        
        //开始取消订单状态
        $res = $this->orderCancelChange($param);
        if( $res['code'] != Normal::SUC ) {
            OrderSupplier::instance()->rollback();
            return Normal::returnCode(Normal::FAIL,"取消订单失败，请稍后再试！");
        }
        
        //开始恢复库存
        $res = $this->recoverGoodsStock($param);
        if( $res['code'] != Normal::SUC ) {
            OrderSupplier::instance()->rollback();
            return Normal::returnCode(Normal::FAIL,$res['msg']);
        }
        
        $res['data']['orderItem']['orderSn'] = $supplierOrder['order_sn'];
        $res['data']['orderItem']['orderNo'] = $supplierOrder['supplier_csn'];
        
        //云仓商城已支付订单不进行结算，推送结算消息数据
        $binfo = Business::instance()->getUserInfoByBid($supplierOrder['bid']);
        if( $supplierOrder['order_status'] == 1 && $supplierOrder['order_type'] != 1 && $binfo['is_skip_settlement'] != 1 ) {
            //恢复临时结算数据
            PushOrderSettleMentService::instance()->removeOrderSettleMentLog([
                'supplierOrder' => $supplierOrder,
                'binfo'         => $binfo,
                'mode'          => PushOrderSettleMentService::SETTLEMENT_MODE_AFTER_SALE,
            ]);
        }
        
        OrderSupplier::instance()->commit();
        return Normal::returnCode(Normal::SUC,"取消成功",$res);
    }
    
    /**
     * 单个订单取消
     * @param array $param
     */
    public function singleOrderCancel( $param = [] )
    {
        if( empty($param['companyInfo']) || empty($param['supplierOrder']) || empty($param['orderGoods']) || empty($param['order']) || empty($param['binfo']) )
        {
            return Normal::returnCode(Normal::FAIL,"except param companyInfo or supplierOrder or orderGoods or order or binfo");
        }
        
        $binfo          = $param['binfo'];
        $supplierOrder  = $param['supplierOrder'];
        $orderGoods     = $param['orderGoods'];
        $companyInfo    = $param['companyInfo'];
        $param['apiBody'] = $companyInfo['apiBody'];
        $company_code   = $companyInfo['company_code'];
        $supplierClass  = ucFirst( $companyInfo['OrderDockMode'] == 1 ? 'normal' : $companyInfo['company_code'] );
        $serviceClass   = "App\\Service\\OrderService\\OrderRouteService\\{$supplierClass}";
        if( !class_exists($serviceClass) )
        {
            return Normal::returnCode(Normal::FAIL,"{$serviceClass} not existed");
        }
        
        $requestMethod = 'orderCancel';
        if( !method_exists($serviceClass,$requestMethod))
        {
            return Normal::returnCode(Normal::FAIL,"{$serviceClass} {$requestMethod} methods not existed");
        }
        
        OrderSupplier::instance()->startTrans();
        
        //修改订单状态
        $res = $this->orderCancelChange($param);
        if( $res['code'] != Normal::SUC ) {
            OrderSupplier::instance()->rollback();
            return $res;
        }
        
        
        //调用对应供应商接口取消
        $res = $serviceClass::instance()->$requestMethod($param);
        if( $res['code'] != Normal::SUC ) {
            OrderSupplier::instance()->rollback();
            return $res;
        }
        
        //取消成功
        if( isset($res['data']) && is_string($res['data']) ) {
            $message = $res['data'];
            unset($res['data']);
            $res['data']['message'] = $message;
        }
        
        $res['data']['orderItem']['orderSn']      = $supplierOrder['order_sn'];
        $res['data']['orderItem']['supplier_csn'] = $supplierOrder['supplier_csn'];
        $res['data']['orderItem']['supplier_dsn'] = $supplierOrder['supplier_dsn'];
        $res['data']['orderItem']['supplier_psn'] = $supplierOrder['supplier_psn'];
        
        //提交事务之前，发布消息
        if( !isset(OrderCreateVolidate::$sensitive_user[$binfo['user_tag']]) )
        {
            $result = OSELMS::instance()->publish((string)$supplierOrder['id'],OSELMS::EVENT_TYPE_ORDER_CANCEL, "发起订单取消");
            if( $result['code'] != Normal::SUC )
            {
                OrderSupplier::instance()->rollback();
                return Normal::returnCode(Normal::FAIL,"系统内部异常，请稍后再试【{$result['msg']}】");
            }
        }
        
        //提交事务
        OrderSupplier::instance()->commit();
        //恢复库存
        $this->recoverGoodsStock($param);
        return $res;
    }

    /**
     * 获取供应商列表
     * @param array $param
     */
    public function getSupplierOrderLists( $param = [] )
    {
        $bid = $param['binfo']['bid'];
        $query = OrderSupplier::instance()
        ->select(OrderSupplier::instance()->order_fields)
        ->where('bid',$bid)
        ->where('order_status',0)
        ->where('order_sn',$param['requestData']['orderSn']);
        
        if( !empty($param['requestData']['orderNo']) ) {
            $query->where('supplier_csn',$param['requestData']['orderNo']);
        }
        
        $supplierOrderList = $query->get()->toArray();
        if( empty($supplierOrderList) ) {
            return Normal::returnCode(Normal::FAIL,"当前订单不存在或已取消");
        }
        
        //获取订单商品
        $osids  = array_column($supplierOrderList,'id');
        $orderGoods = OrderSupplierGoods::instance()
        ->select(OrderSupplierGoods::instance()->goods_fields)
        ->where('bid',$bid)
        ->whereIn('order_id',$osids)
        ->get()
        ->toArray();
        
        if( empty($orderGoods) ) {
            return Normal::returnCode(Normal::FAIL,"获取订单数据失败");
        }
        
        $newOrderGoods = [];
        foreach ($orderGoods as $item ) {
            $newOrderGoods[$item['order_id']][] = $item;
            unset($item);
        }
        
        //获取供应商清单信息
        $companyIds = array_unique(array_column($supplierOrderList,'company_id'));
        $SupplierCompanyLists = SupplierCompany::instance()->getSupplierListByIds($companyIds);
        $SupplierCompanyLists = array_column($SupplierCompanyLists, null,'company_id');
        
        return Normal::returnCode(Normal::SUC,"订单数据获取成功",[
            'supplierOrderList' => $supplierOrderList,
            'newOrderGoods' => $newOrderGoods,
            'suppplierList' => $SupplierCompanyLists
        ]);
    }
    
    
    /**
     * 取消订单公共接口
     */
    public function orderCancelChange( $param  = [] )
    {
        $order      = $param['order'];
        $orderInfo  = $param['supplierOrder'];
        $time       = time();
        
        //取消订单原因
        $source        = isset($order['source']) ? $order['source'] : '';
        $exceptReason  = "【{$source}】".$order['exceptReason'];
        $query = OrderSupplier::instance()->where('id',$orderInfo['id']);
        //已支付的订单，走售后状态，不修改支付状态到取消状态
        if( $orderInfo['order_status'] == 1 ) {
            $data = [
                'after_sale_status'     => 1,
                'md'                    => $time,
                'cancel_remark'         => $exceptReason,
            ];
            //供应商发起取消
            if( isset($order['is_supplier_cancel']) && $order['is_supplier_cancel'] == 1 ) {
                //云仓商城订单，取消之后，直接到退款状态
                if( $orderInfo['order_type'] == 1 ) {
                    OrderReturnLog::instance()->addLog([
                        'order_id'          =>  $supplierOrder['id'],
                        'type'              =>  OrderReturnLog::AFTER_PASS,
                        'contents'          =>  "上游供应商针对中台的订单发起取消动作，直接到待退款状态",
                        'system_user_id'    =>  $supplierOrder['bid'],
                        'system_user_name'  =>  "供应商",
                    ]);
                    $data = [
                        'after_sale_status'     => 1,
                        'after_verify_status'   => 1,
                        'after_verify_remark'   => '供应商取消订单自动审核通过',
                        'after_verify_time'     => $time,
                        'md'                    => $time,
                        'cancel_remark'         => $exceptReason,
                    ];
                } 
            }
            $query->where('order_status',1);
        } else {
            $query->whereIn('order_status',[0,200]);
            $data = [
                'order_status'      => 100,
                'md'                => $time,
                'cancel_remark'     => $exceptReason,
            ];
        }
        
        $resId = $query->update($data);
        if( !$resId ) {
            return Normal::returnCode(Normal::FAIL,"取消订单失败-1");
        }
        
        return Normal::returnCode(Normal::SUC,"操作成功");
    }

    /**
     * 恢复总部库存接口
     */
    public function recoverGoodsStock( $param  = [] )
    {
        $orderGoods = $param['orderGoods'];
        $binfo = $param['binfo'];
        $notifyReduceStock = [];
        foreach ($orderGoods as $item ) {
            if( isset($item['is_deduct_stock']) && $item['is_deduct_stock'] == 1 ) {
                $notifyReduceStock[] = [
                    'SkuID'                 => $item['goods_id'],
                    'warehouseID'           => (string)$item['store_id'],
                    'stockInfoID'           => (string)$item['stock_id'],
                    'goodsName'             => $item['goods_name'],
                    'number'                => (int)(bcmul((string)$item['quantity'], (string)$item['spec_num'],2))
                ];
            }
        }
        
        if( empty($notifyReduceStock) ) {
            return Normal::returnCode(Normal::SUC,"当前无需扣除库存");
        }
        return CommodityStockService::instance()->orderReduceStock((int)$binfo['bid'],$notifyReduceStock,'+');
    }
}